#! /usr/bin/env python3
# -*- coding: UTF-8 -*-

try:
    from package.litedb import litedb
except:
    pass

try:
    from litedb import *
except:
    pass

import re
import time


def tracelog_to_csv(log, csv):
    i = 0
    flog = open(log, 'r')
    fcsv = open(csv, 'w')
    for row in flog:
        i += 1
        try:
            if 'kmalloc:' in row:
                row = re.sub('[\[\]:]|ptr=|bytes_alloc=', '', row)
                col = row.split()
                task, pid = col[0].rsplit('-', 1)
                fcsv.write(f'{task} {pid} {col[1]} {col[2]} {col[3]} {col[6]} {col[8]}\n')
            elif 'kfree:' in row:
                row = re.sub('[\[\]:]|ptr=', '', row)
                col = row.split()
                task, pid = col[0].rsplit('-', 1)
                fcsv.write(f'{task} {pid} {col[1]} {col[2]} {col[3]} {col[6]} 0\n')
        except Exception as e:
            print(f'line: {i} exception: {e}')
    fcsv.close()
    flog.close()

def func():
    for row0 in csv:
        if 'kmalloc' not in row0:
            continue

    pass

def tracelog_call_to_csv(log, csv, call_csv):
    flog = open(log, 'r')
    fcsv = open(csv, 'r')
    fcall = open(call_csv, 'w')

    line = next(flog)
    row = next(fcsv)
    col = row.split()
    is_call_on = False
    have_csv = True

    while True:
        # log/time
        if col[3] in line and 'kmalloc:' in line and re.search(f'{col[0]}-{col[1]}\s*\[.*{col[2]}\]', line):
            while True:
                if is_call_on:
                    # log/call data
                    if '=>' in line:
                        call = line.split()[1]
                        fcall.write(f'{call}|')
                    # log/call end
                    else:
                        fcall.write('\n')
                        is_call_on = False
                        # csv/alloc
                        for row in fcsv:
                            if 'kmalloc' in row:
                                col = row.split()
                                break
                        break
                else:
                    # log/kernel_stack
                    if 'kernel_stack:' in line and re.search(f'{col[0]}-{col[1]}\s*\[.*{col[2]}\]', line):
                        is_call_on = True

                line = next(flog)
            # end-while
        else:
            line = next(flog)
    # end-while
    fcall.close()
    fcsv.close()
    flog.close()


def create_table(db):
    db.sql(f"drop table if exists 'trace'")
    db.sql(f"create table 'trace' (id integer primary key autoincrement, task, pid integer, cpu integer, time float, func, ptr, bytes integer, calls, flag0)")
    db.save()

def insert_table(db, csv):
    f = open(csv, 'r')
    for row in f:
        col = row.split()
        values = f"'{col[0]}', {col[1]}, {col[2]}, {col[3]}, '{col[4]}', '{col[5]}', {col[6]}"
        db.sql(f"insert into 'trace' (task, pid, cpu, time, func, ptr, bytes) values ({values})")
    db.save()
    f.close()

def insert_table_call(db, csv):
    pass

def load_csv(csv='trace.csv'):
    db = litedb()
    db.open('trace.db')
    create_table(db)
    insert_table(db, 'trace.csv')
    db.close()

def load_tracelog(log='trace.log'):
    csv = 'trace.csv'

    print(f'load  {log}')
    t0 = time.time()
    tracelog_to_csv(log, csv)
    t1 = time.time()
    print(f'time  {t1-t0:.2f} sec')

    print(f'load  {csv}')
    t0 = time.time()
    load_csv(csv)
    t1 = time.time()
    print(f'time  {t1-t0:.2f} sec')

def load_bpflog():
    pass

if __name__ == '__main__':
    import time
    import sys

    t0 = time.time()
    #load_tracelog(sys.argv[1])
    tracelog_call_to_csv('trace.log', 'trace.csv', 'trace.call.csv')
    t1 = time.time()
    print(f'time:{t1-t0:.4f}')
